package com.sunday.common.netty.e4_TCP.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TcpServer {

    public static final int SERVER_PORT = 8811;

    public static void main(String[] args) throws InterruptedException {

        log.info("Begin to start TCP server on port: {}.....", SERVER_PORT);

        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    // NioServerSocketChannel.class: 异步 TCP 服务端, 最常用的Server Channel。
                    .channel(NioServerSocketChannel.class)
                    // ChannelOption.SO_BACKLOG: 服务端接受连接的队列长度，如果队列已满，客户端连接将被拒绝。 默认 50。
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    // ChannelOption.AUTO_CLOSE: 一旦连接，就会自动关闭。 默认 false。
                    .option(ChannelOption.AUTO_CLOSE, true)
                    // ChannelOption.SO_REUSEADDR: 允许重复使用本地地址和端口。 默认 false。
                    .option(ChannelOption.SO_REUSEADDR, true)
                    // TcpServerChannel 是一个 ChannelInitializer，用于初始化 SocketChannel。
                    .childHandler(new TcpServerChannel())
                    // ChannelOption.SO_KEEPALIVE: 保持连接。
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // ChannelOption.TCP_NODELAY: 关闭 Nagle 算法。
                    .childOption(ChannelOption.TCP_NODELAY, true);

            ChannelFuture f = b.bind(SERVER_PORT).sync();
            log.info("Server started.");
            f.addListener(future -> log.info("Server Bind future complete."));
            f.channel()
                    .closeFuture()
                    .addListener(future -> log.info("Server Channel future complete."))
                    .sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }

}
